/**
 * @constructor
 */
function MovingUnitGameEntity(startCellX, startCellY, 
		destinationCellX,
		destinationCellY,
		speed,
		cellSize, 
		
		animationBundle,
		
		area,
		terrainOnlyArea) {
	
	$.extend(this,new GameEntity(startCellX*cellSize, startCellY*cellSize, cellSize, cellSize));
	
	this.destinationCellX = destinationCellX;
	this.destinationCellY = destinationCellY;
	
	this.speed = speed;
	this.direction = new Direction(0, 0);
	
	this.cellSize = cellSize;
	this.diagonalSpeed = speed/1.4;
	
	this.animationBundle = animationBundle;
	this.currentAnimation;
	if(DEBUG_MODE) {
		if(destinationCellX > CANVAS_CELLS_X/2) {
			this.currentAnimation = this.animationBundle.debugRight;
		} else {
			this.currentAnimation = this.animationBundle.debugLeft;
		}
	} else {
		if(destinationCellX > CANVAS_CELLS_X/2) {
			this.currentAnimation = this.animationBundle.standRight;
		} else {
			this.currentAnimation = this.animationBundle.standLeft;
		}
	}
	this.currentAnimation.start();
		
	this.area = area;
	this.terrainOnlyArea = terrainOnlyArea;
	
	this.currentX = startCellX*cellSize;
	this.currentY = startCellY*cellSize;
	
	this.finiteStateMachine = new MovingUnitFiniteStateMachine(this);
	
	this.totalPathCalculatingDurationMs = 0;
	
	this.manager;
	
	/**
	 * @public
	 */
	this.processInput = function(inputEvent) {
		if(inputEvent instanceof MoveInputEvent) {
			this.finiteStateMachine.onUnitProcessInput(inputEvent);
		} else if(inputEvent instanceof ToggleDebugEvent) {
			if(inputEvent.value == true) {
				if(this.finiteStateMachine.currentState instanceof MovingUnitStandState || 
						this.finiteStateMachine.currentState instanceof MovingUnitWaitForBetterPathState) {
					//these states set the animation only when they are inited, hence they won't change the animation by themselves when
					//the DEBUG_MODE flag is changed
					if(this.currentAnimation === this.animationBundle.standLeft) {
						this.currentAnimation = this.animationBundle.debugLeft;
					} else {
						this.currentAnimation = this.animationBundle.debugRight;
					}
				}
			} else {
				if(this.finiteStateMachine.currentState instanceof MovingUnitStandState || 
						this.finiteStateMachine.currentState instanceof MovingUnitWaitForBetterPathState) {
					//these states set the animation only when they are inited, hence they won't change the animation by themselves when
					//the DEBUG_MODE flag is changed
					this.currentAnimation = this.animationBundle.standDown;
				}
			}
			this.currentAnimation.start();
		} 		
	};
	
	/**
	 * @public
	 */
	this.updateState = function() {
		this.finiteStateMachine.onUnitUpdateState();
		this.currentAnimation.onGameStateUpdate();
	};
	
	/**
	 * @public
	 * @param{Context} canvas
	 */
	this.updateGraphics = function(context) {
		//draw path:
//		var evaluatePathState = this.finiteStateMachine.movingUnitStates[this.finiteStateMachine.movingUnitStatesEnum.EVALUATE_PATH_ADVANCEMENT];
//		var path = evaluatePathState.path;
//		if(path!=null && path.nodes.length>1) {
//			context.fillStyle = "#D8D8D8";//gray
//			for(var i=evaluatePathState.currentNodeIdx; i<path.nodes.length; i++) {
//				var node = path.nodes[i];
//				context.fillRect(node.x*this.cellSize+this.cellSize/4, node.y*this.cellSize+this.cellSize/4, this.width/2, this.height/2);
//			}
//		}
		
		//draw sprite image:
		this.currentAnimation.onGraphicsUpdate(context, this.currentX, this.currentY);	
		
		if(DEBUG_MODE) {
			//draw finite state machine state visual aid:		
			if(!(this.finiteStateMachine.currentState instanceof MovingUnitStandState)) {
				var color;
				if(this.finiteStateMachine.currentState instanceof MovingUnitCalculatePathState) {
					color = "#FF0000"; //red
				} else if(this.finiteStateMachine.currentState instanceof MovingUnitEvaluatePathAdvancementState) {
					color = "#FF9900"; //orange
				} else if(this.finiteStateMachine.currentState instanceof MovingUnitMoveBetweenPathNodesState) {
					color = "#00FF00"; //green
				} else if(this.finiteStateMachine.currentState instanceof MovingUnitWaitForBetterPathState) {
					color = "#000000"; //black
				}
				context.strokeStyle=color;
				context.lineWidth=2;
				context.strokeRect(this.currentX, this.currentY, this.width, this.height);
			}
		}
	};
	
	this.switchPositionSide = function() {
		var temp = this.destinationCellX;
		this.destinationCellX = this.startX/this.cellSize;
		this.startX = temp * this.cellSize;
		this.currentX = this.startX;
		
		if(DEBUG_MODE) {
			if(this.destinationCellX > CANVAS_CELLS_X/2) {
				this.currentAnimation = this.animationBundle.debugRight;
			} else {
				this.currentAnimation = this.animationBundle.debugLeft;
			}
		} else {
			if(this.destinationCellX > CANVAS_CELLS_X/2) {
				this.currentAnimation = this.animationBundle.standRight;
			} else {
				this.currentAnimation = this.animationBundle.standLeft;
			}
		}
		this.currentAnimation.start();
		
		this.totalPathCalculatingDurationMs = 0;		
	};
}

function Direction(xDirection, yDirection) {
	this.x = xDirection;
	this.y = yDirection;
	
	this.update = function(prevX, prevY, curX, curY) {
		this.x = this.sgn(curX - prevX);
		this.y = this.sgn(curY - prevY);
	};
	
	this.isDiagonal = function() {
		return this.x != 0 && this.y != 0;
	};
	
	this.sgn = function(a) {
		return a?a<0?-1:1:0;
	};
}

